package com.aiatomic.countlib;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.dyve.counting.CountingManager;
import com.google.gson.Gson;

import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {
    TextView tvInfo;
    Button btnRegister;
    Button btnClose;
    int count = 0;
    ServerSocket serverSocket = null;
    String localIp;
    String port;
    ArrayBlockingQueue<TaskQueue> queue = new ArrayBlockingQueue<>(100);
    boolean blockTask = false;
    private MsgManager msgManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        localIp = getLocalIpAddress();
        setContentView(R.layout.activity_main);
        tvInfo = findViewById(R.id.tvInfo);
        btnRegister = findViewById(R.id.btnRegister);
        btnClose = findViewById(R.id.btnClose);
        btnClose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                btnClose.setEnabled(false);
                unregister();
            }
        });
        btnRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                btnRegister.setEnabled(false);
                readIpConfig();
            }
        });
        TplInitService.init(this);
        readIpConfig();
    }

    private void readIpConfig() {
        tvInfo.setText("本机IP:" + localIp + "\n");
        tvInfo.append("绑定端口:待服务端返回\n");
        tvInfo.append("正在等待服务端分配端口...\n");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    autoRegister();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public String getLocalIpAddress() {
        try {
            NetworkInterface intf = NetworkInterface.getByName("eth0");
            if (intf == null) {
                intf = NetworkInterface.getByName("wlan0");
            }
            List<InterfaceAddress> list = intf.getInterfaceAddresses();
            if (list != null) {
                for (InterfaceAddress address : list) {
                    if (address.getBroadcast() != null) {
                        return address.getAddress().getHostAddress();
                    }
                }
            }
        } catch (SocketException ex) {
            Log.e("WifiPreferenceIpAddress", ex.toString());
        }
        return null;
    }

    private void startServer(final int port) {
        new Thread() {
            @Override
            public void run() {
                try {
                    serverSocket = new ServerSocket(port, 50, InetAddress.getLocalHost());
                    Log.e("LIB", "服务启动成功！");
                    tvInfo.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "服务启动成功", Toast.LENGTH_LONG).show();
                            tvInfo.setText("本机IP:" + localIp + "\n");
                            tvInfo.append("绑定端口:" + port + "\n");
                            tvInfo.append("服务启动成功!\n");
                            btnRegister.setVisibility(View.GONE);
                            btnClose.setVisibility(View.VISIBLE);
                            btnClose.setEnabled(true);
                        }
                    });
                    startQueue();
                    while (true) {
                        Socket accept = serverSocket.accept();
                        count++;
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                tvInfo.setText("本机IP:" + localIp + "\n");
                                tvInfo.append("绑定端口:" + port + "\n");
                                tvInfo.append("服务已启动:\n");
                                tvInfo.append("当前连接数:" + count);
                            }
                        });
                        addQueue(accept);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void startQueue() {
        blockTask = false;
        new Thread() {
            @Override
            public void run() {
                while (!blockTask) {
                    TaskQueue taskQueue = null;
                    try {
                        taskQueue = queue.take();
                        InputStream inputStream = null;
                        OutputStream outputStream = null;
                        try {
                            inputStream = taskQueue.inputStream;
                            Bitmap bitmap = ReadHelper.readBitmap(inputStream);
                            String type = ReadHelper.read(inputStream);
                            String config = ReadHelper.read(inputStream);
                            Log.e("LIB", "Read Over config=" + config);
                            if (bitmap == null || type == null || config == null) {
                                outputStream = taskQueue.outputStream;
                                Result result = new Result();
                                result.count = 0;
                                result.lastError = "请求参数有误";
                                result.success = false;
                                WriteHelper.sendData(outputStream, new Gson().toJson(result));
                            } else {
                                Result result = new Result();
                                result.count = CountingManager.count(bitmap, null, Integer.parseInt(type), path(config));
                                result.lastError = CountingManager.getLastError();
                                result.success = true;
                                if (result.count > 0) {
                                    final int[] paramArrayOfInt1 = new int[result.count];
                                    final int[] paramArrayOfInt2 = new int[result.count];
                                    final int[] paramArrayOfInt3 = new int[result.count];
                                    final int[] paramArrayOfInt4 = new int[result.count];
                                    final int[] paramArrayOfInt5 = new int[result.count];
                                    CountingManager.getResults(paramArrayOfInt1, paramArrayOfInt2, paramArrayOfInt3, paramArrayOfInt4, paramArrayOfInt5);
                                    result.paramArrayOfInt1 = paramArrayOfInt1;
                                    result.paramArrayOfInt2 = paramArrayOfInt2;
                                    result.paramArrayOfInt3 = paramArrayOfInt3;
                                    result.paramArrayOfInt4 = paramArrayOfInt4;
                                    result.paramArrayOfInt5 = paramArrayOfInt5;
                                }
                                outputStream = taskQueue.outputStream;
                                WriteHelper.sendData(outputStream, new Gson().toJson(result));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (inputStream != null) {
                                    inputStream.close();
                                }
                                if (outputStream != null) {
                                    outputStream.close();
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            count--;
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    tvInfo.setText("本机IP:" + localIp + "\n");
                                    tvInfo.append("绑定端口:" + port + "\n");
                                    tvInfo.append("服务已启动:\n");
                                    tvInfo.append("当前连接数:" + count);
                                }
                            });
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    public void addQueue(final Socket socket) throws IOException {
        TaskQueue taskQueue = new TaskQueue();
        taskQueue.inputStream = socket.getInputStream();
        taskQueue.outputStream = socket.getOutputStream();
        try {
            queue.put(taskQueue);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void unregister() {
        new Thread() {
            @Override
            public void run() {
                try {
                    if (msgManager != null) {
                        msgManager.disconnect(new MsgManager.OnDisconnectSuccessListener() {
                            @Override
                            public void onDisconnect() {
                                try {
                                    queue.clear();
                                    blockTask = true;
                                    if (serverSocket != null) {
                                        serverSocket.close();
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                                Log.e("LIB", "服务注销成功！");
                                btnRegister.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(MainActivity.this, "服务注销成功", Toast.LENGTH_LONG).show();
                                        tvInfo.setText("本机IP:" + localIp + "\n");
                                        tvInfo.append("绑定端口:" + port + "\n");
                                        tvInfo.append("服务未注册！\n");
                                        btnRegister.setVisibility(View.VISIBLE);
                                        btnRegister.setEnabled(true);
                                        btnClose.setVisibility(View.GONE);
                                    }
                                });
                            }
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    btnClose.post(new Runnable() {
                        @Override
                        public void run() {
                            btnClose.setEnabled(true);
                        }
                    });
                }
            }
        }.start();
    }

    private void autoRegister() {
        try {
            msgManager = new MsgManager();
            msgManager.connect(localIp, new MsgManager.OnConnectSuccessListener() {
                @Override
                public void onConnect(final String port) {
                    MainActivity.this.port = port;
                    tvInfo.post(new Runnable() {
                        @Override
                        public void run() {
                            tvInfo.setText("本机IP:" + localIp + "\n");
                            tvInfo.append("绑定端口:" + port + "\n");
                            tvInfo.append("正在注册服务到服务端...\n");
                        }
                    });
                    startServer(Integer.parseInt(port));
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            moveTaskToBack(true);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onBackPressed() {
        moveTaskToBack(true);
    }

    private String path(String config) {
        return new File(getExternalCacheDir(), config).getAbsolutePath();
    }
}
